/*
 * Copyright 2011 Kim Lindhardt Madsen
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package dk.lindhardt.gwt.geie.client;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTMLTable;
import com.google.gwt.user.client.ui.Widget;
import dk.lindhardt.gwt.geie.client.edit.HTMLTablePresenter;
import dk.lindhardt.gwt.geie.client.edit.HTMLTablePresenterImpl;
import dk.lindhardt.gwt.geie.client.evaluate.GeieFormulaCalculator;
import dk.lindhardt.gwt.geie.shared.*;

import java.util.List;
import java.util.Map;

/**
 * User: AnAmuser
 * Date: 24-05-11
 * <p/>
 * Class for building a {@link com.google.gwt.user.client.ui.FlexTable} from a {@link TableLayout}
 */
public class TableLayout2FlexTable {

   private Map<CellFormatKey, CellFormat> cellFormats;
   private FlexTable table;
   private TableLayout layout;
   private HTMLTablePresenter tablePresenter = new HTMLTablePresenterImpl();
   private ElementStyler tableStyler = new DefaultElementStyler();
   private TableMouseEventHandler mouseEventHandler;

   /**
    * TableLayout can be both EXCEL and HTML structured. It will be converted to HTML structure before build.
    * @param layout the layout
    */
   public TableLayout2FlexTable(TableLayout layout) {
      this.layout = layout;
      this.cellFormats = layout.getCellFormats();
   }

   /**
    * Sets alternative table presenter. If this is set to null the cells will not be editable. The tablePresenter
    * defaults to {@link dk.lindhardt.gwt.geie.client.edit.HTMLTablePresenterImpl}.
    * @param tablePresenter the table presenter
    */
   public void setTablePresenter(HTMLTablePresenter tablePresenter) {
      this.tablePresenter = tablePresenter;
   }

   /**
    * Sets alternative styler on the table. If this is set to null the cells will not be styled except for height width
    * which is still set. The styler defaults to {@link DefaultElementStyler}
    * @param tableStyler  the styler
    */
   public void setTableStyler(ElementStyler tableStyler) {
      this.tableStyler = tableStyler;
   }

   /**
    * Builds a {@link com.google.gwt.user.client.ui.FlexTable} from a {@link TableLayout} and handles the styling of
    * the table.
    * @return the flex table
    */
   public FlexTable build() {
      table = new FlexTable();
      table.setCellPadding(0);
      table.setCellSpacing(0);

      GeieFormulaCalculator formulaCalculator = new GeieFormulaCalculator(layout);
      formulaCalculator.calculateAllFormulas();

      createAndStyleCells();
      createHeightsAndWidths();

      if (tablePresenter != null) {
         mouseEventHandler = new TableMouseEventHandler(layout, table, tablePresenter);
         tablePresenter.setContext(layout, table, tableStyler, mouseEventHandler);
      }

      return table;
   }

   private void createHeightsAndWidths() {
      Map<Integer, Integer> rowHeights = layout.getRowHeights();
      for (Integer rowIndex : rowHeights.keySet()) {
         if (rowIndex < table.getRowCount()) {
            Element row = table.getRowFormatter().getElement(rowIndex);
            DOM.setStyleAttribute(row, "height", rowHeights.get(rowIndex).toString());
         }
      }

      Map<Integer, Integer> columnWidths = layout.getColumnWidths();
      for (Integer columnIndex : columnWidths.keySet()) {
         Element column = table.getColumnFormatter().getElement(columnIndex);
         DOM.setStyleAttribute(column, "width", columnWidths.get(columnIndex).toString());
      }
   }

   private void createAndStyleCells() {
      List<Cell> cells = layout.getCells();
      ColumnCorrectionBookKeeper bookKeeper = layout.getColumnCorrectionBookKeeper();
      for (Cell cell : cells) {
         Position position = bookKeeper.applyCorrection(cell.getPosition(), PositioningType.HTML);
         Widget widget = getCellContent(cell);
         int row = position.getRow();
         int column = position.getColumn();
         table.setWidget(row, column, widget);
         if (position.getSpanColumn() > 0) {
            table.getFlexCellFormatter().setColSpan(row, column, position.getSpanColumn());
         }
         if (position.getSpanRow() > 0) {
            table.getFlexCellFormatter().setRowSpan(row, column, position.getSpanRow());
         }

         if (tableStyler != null) {
            Element element = table.getCellFormatter().getElement(row, column);
            CellFormat cellFormat = layout.getCellFormat(cell.getCellFormatKey());
            tableStyler.styleElement(element, cellFormat);
         }
      }
   }

   private Widget getCellContent(Cell cell) {
      CellFormat cellFormat = cellFormats.get(cell.getCellFormatKey());
      return cell.toWidget(cellFormat);
   }
}
